﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Text.RegularExpressions;
using System.IO;
using My.GenCode.Entities;

namespace My.GenCode.Interface
{

    public abstract class CodeTemplate
    {
        // 单实体处理
        protected string _tpl = null;
        protected EntityInfo _info = null;
        protected NameHelper _nh = null;

        // 多实体处理
        protected IList<EntityInfo> _infos = null;

        #region 构造方法
        /// <summary>
        /// 单实体构造函数，已重载
        /// </summary>
        /// <param name="tpl"></param>
        /// <param name="info"></param>
        public CodeTemplate(string tpl, EntityInfo info,string desc)
        {
            _tpl = tpl;
            _info = info;
            _nh = new NameHelper(_info.Name, _info.Service, _info.Company);
            Description = desc;
        }

        /// <summary>
        /// 多实体构造函数，已重载
        /// </summary>
        /// <param name="tpl"></param>
        /// <param name="infos"></param>
        /// <param name="desc"></param>
        public CodeTemplate(string tpl, IList<EntityInfo> infos,string desc) : this(tpl,infos[0],desc)
        {
            _infos = infos;
        }
        
        #endregion

        #region 核心方法(模板方法模式)

        /// <summary>
        /// 生成代码
        /// </summary>
        /// <returns></returns>
        public string Generate()
        {
            _tpl = this.ProcTemplate();

            _tpl = _tpl.Replace("<Description>", Description);                       // 处理<Description>标签
            _tpl = _tpl.Replace("<DateTime.Now>", DateTime.Now.ToString());          // 处理<DateTime.Now>标签
            _tpl = _tpl.Replace("<DateTime.Now.Year>", DateTime.Now.Year.ToString());// 处理<DateTime.Now.Year>标签 
            _tpl = _tpl.Replace("<Copyright>", _info.CopyRight);                     // 处理<Copyright>标签 

            return _tpl;
        }
        
        /// <summary>
        /// 生成文件
        /// </summary>
        /// <param name="path"></param>
        public string Generate(string path)
        {
            string s = this.Generate();
            path = Path.Combine(path,this.OutputFilename());
            Directory.CreateDirectory(Path.GetDirectoryName(path));
            File.WriteAllText(path, s);
            return s;
        }

        #endregion

        #region 抽象方法
        /// <summary>
        /// 处理模板
        /// </summary>
        /// <param name="tpl"></param>
        /// <returns></returns>
        protected abstract string ProcTemplate();

        /// <summary>
        /// 代码的输出文件名
        /// </summary>
        /// <returns></returns>
        protected abstract string OutputFilename();
        #endregion

        #region 属性

        /// <summary>
        /// 类描述
        /// </summary>
        private string _Description;
        public string Description
        {
            get { return _Description; }
            set { _Description = value; }
        }

        #endregion

        #region 工具方法
        /// <summary>
        /// 处理[loop<Properties>][/loop]标签
        /// </summary>
        /// <param name="tpl"></param>
        /// <returns></returns>
        protected string LoopProperties(string tpl, string loopTag, ReplaceProperty fnReplace)
        {
            string regCodeBlock = @"(?s)\[(loop"+ loopTag + @")](.*)\[/\1]";

            Match m = Regex.Match(tpl, regCodeBlock);
            string thisTpl = m.Groups[2].Value;

            List<string> list = new List<string>();
            foreach (PropertyInfo p in _info.Properties)
            {
                list.Add(fnReplace(thisTpl, p));
            }

            string s = string.Join("", list.ToArray());
            return Regex.Replace(tpl, regCodeBlock, s);
        }

        /// <summary>
        /// 处理[loop<Entities>][/loop]标签
        /// </summary>
        /// <param name="tpl"></param>
        /// <param name="loopTag"></param>
        /// <param name="fnReplace"></param>
        /// <returns></returns>
        protected string LoopEntities(string tpl, string loopTag, ReplaceEntity fnReplace)
        {
            string regCodeBlock = @"(?s)\[(loop" + loopTag + @")](.*)\[/\1]";

            Match m = Regex.Match(tpl, regCodeBlock);
            string thisTpl = m.Groups[2].Value;
            List<string> list = new List<string>();

            foreach (EntityInfo e in _infos)
            {
                list.Add( fnReplace(thisTpl, e) );
            }

            string s = string.Join("", list.ToArray());
            return Regex.Replace(tpl, regCodeBlock, s);
        }

        /// <summary>
        /// 处理属性子模板委托
        /// </summary>
        /// <param name="subtpl"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        protected delegate string ReplaceProperty(string tpl,PropertyInfo info);
        
        /// <summary>
        /// 处理实体子模板
        /// </summary>
        /// <param name="tpl"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        protected delegate string ReplaceEntity(string tpl, EntityInfo info);
        
        #endregion

    }
}